package vn.mahjonggame.zone.request;

import vn.mahjonggame.util.Common;

import java.text.SimpleDateFormat;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Enumeration;

import org.apache.log4j.Appender;
import org.apache.log4j.FileAppender;
import org.apache.log4j.LogManager;
import org.apache.log4j.Logger;

import vn.mahjonggame.util.PropertiesCache;
import vn.mahjonggame.zone.MahjongZoneExtension;
import vn.mahjonggame.game.MahjongExtension;
import vn.mahjonggame.metadata.ConfigObject;
import vn.mahjonggame.metadata.GameActionType;
import vn.mahjonggame.metadata.MatchState;
import vn.mahjonggame.metadata.PlayerMode;
import vn.mahjonggame.metadata.ResponseCode;
import vn.mahjonggame.metadata.MObject;
import vn.mahjonggame.metadata.RoomVarName;
import vn.mahjonggame.metadata.UserVarName;
import vn.mahjonggame.platform.GameplayConfig;
import vn.mahjonggame.platform.PlatformClient;
import vn.mahjonggame.platform.PlatformConfig;

import com.smartfoxserver.v2.api.CreateRoomSettings;
import com.smartfoxserver.v2.api.CreateRoomSettings.RoomExtensionSettings;
import com.smartfoxserver.v2.entities.SFSRoomRemoveMode;
import com.smartfoxserver.v2.entities.SFSRoomSettings;
import com.smartfoxserver.v2.entities.User;
import com.smartfoxserver.v2.entities.data.ISFSObject;
import com.smartfoxserver.v2.entities.data.SFSObject;
import com.smartfoxserver.v2.entities.variables.RoomVariable;
import com.smartfoxserver.v2.entities.variables.SFSRoomVariable;
import com.smartfoxserver.v2.exceptions.SFSCreateRoomException;
import com.smartfoxserver.v2.extensions.BaseClientRequestHandler;
import com.smartfoxserver.v2.extensions.ExtensionLogLevel;
import com.smartfoxserver.v2.extensions.SFSExtension;

public class CreateMahjongRoomRequestHandler extends BaseClientRequestHandler {
			
	private static int MAX_PLAYER = 4;
	private static int MAX_SPECTATOR = 0;	
	private static String ROOM_ID = "empty";
	private static String TRANSACTION_ID = "empty";

	@Override
	public void handleClientRequest(User user, ISFSObject params) {		
		MahjongZoneExtension parentExtension = (MahjongZoneExtension)getParentExtension();
		createMahjongRoom(parentExtension, user, params);
	}
	
	public void createMahjongRoom(MahjongZoneExtension parentExtension, User user, ISFSObject params){
		
		setParentExtension(parentExtension);
		int playMode = params.getInt(RoomVarName.playMode.toString());
		
		double userBalance = Double.valueOf(Double.valueOf(PlatformConfig.configMap.get(PlatformConfig.TUTORIAL_BALANCE)));					
		
		String roomName = params.getUtfString(RoomVarName.roomName.toString());
		SFSObject response = null;
		
		if(roomName == null){
			response = new SFSObject();			
			response.putUtfString(MObject.message.toString(), "Room name can not be null");
			
			send(GameActionType.create_fail.toString(), response, user);
			return;
		}			
		
		/*
		 * Get the balance from Widocom
		 */
		if (playMode == PlayerMode.REAL_MODE.ordinal()){
			userBalance = user.getVariable(UserVarName.balance.toString()).getDoubleValue();			
			String access_token = user.getVariable(UserVarName.access_token.toString()).getStringValue();
			
			trace(ExtensionLogLevel.INFO, GameActionType.create.toString() + " Start user_get_balance");			
			response = PlatformClient.user_get_balance(access_token);
			
			if (Common.isApiSuccess(response)) {
				String balanceText = response.getSFSObject("response").get("balance").getObject().toString();
				userBalance = Double.parseDouble(balanceText);
			}
			else {
				response = new SFSObject();
				String msg = "Failed in user_get_balance API";
				response.putUtfString(MObject.message.toString(), msg);
				
				send(GameActionType.create_fail.toString(), response, user);
				trace(ExtensionLogLevel.ERROR, GameActionType.create_fail.toString() + ": " + msg);							
			}
			
			trace(ExtensionLogLevel.INFO, GameActionType.create.toString() + " End user_get_balance");
		}
		
		/*
		 * Check to make sure the player's money is enough to create room
		 */
		int roomBet = 0;
		Integer roomBetD = params.getInt(RoomVarName.roomBet.toString());
		
		if(roomBetD == null){
			response = new SFSObject();			
			response.putUtfString(MObject.message.toString(), "room bet can not be null");
			
			send(GameActionType.create_fail.toString(), response, user);
			return;
		}
		else {
			roomBet = roomBetD;
		}
		
		//int roomDeposit = params.getInt(RoomVarName.roomDeposit.toString());		
		
		if (userBalance < roomBet) {
			SFSObject data = new SFSObject();
			data.putDouble(UserVarName.balance.toString(), userBalance);
			data.putInt(RoomVarName.roomBet.toString(), roomBet);
			
			response = new SFSObject();			
			response.putUtfString(MObject.message.toString(), "your balance is not enough");
			
			send(GameActionType.create_fail.toString(), response, user);
			return;
		}			
		
		String access_token = user.getVariable(UserVarName.access_token.toString()).getStringValue();		
				
		String roomPassword =  params.getUtfString(RoomVarName.roomPassword.toString());
		
		String platform_room_id = ROOM_ID;
		String transaction_id = TRANSACTION_ID;
		
		if (playMode ==  PlayerMode.REAL_MODE.ordinal()) 
		{
			trace(ExtensionLogLevel.INFO, GameActionType.create.toString() + " Start game_create_room");
			SFSObject sfsResponse = PlatformClient.game_create_room(access_token, roomName, roomBet, roomBet);
			
			if (!Common.isApiSuccess(sfsResponse))
			{
				response = new SFSObject();
				response.putUtfString(MObject.message.toString(), "Failed in game_create_room API");				
				send(GameActionType.create_fail.toString(), response, user);
				return;
			}
			
			platform_room_id = sfsResponse.getSFSObject("response").getUtfString(RoomVarName.room_id.toString());
			transaction_id = sfsResponse.getSFSObject("response").getUtfString(RoomVarName.transaction_id.toString());
						
			trace(ExtensionLogLevel.INFO, GameActionType.create.toString() + " End game_create_room");			
			trace(ExtensionLogLevel.INFO, "new room_id: " + platform_room_id);
			trace(ExtensionLogLevel.INFO, "new transaction_id: " + transaction_id);			
		}			
		
		/*
		 * Build the room variable
		 */		
        RoomVariable varRoomBet = new SFSRoomVariable(RoomVarName.roomBet.toString(), roomBet);
        varRoomBet.setOwner(null);
        varRoomBet.setPrivate(true);
        varRoomBet.setGlobal(true);
        
        RoomVariable varState = new SFSRoomVariable(RoomVarName.roomState.toString(), MatchState.WAIT_MORE_PLAYERS.ordinal());
        varState.setOwner(null);
        varState.setPrivate(true);
        varState.setGlobal(true);
        
        RoomVariable varPlayMode = new SFSRoomVariable(RoomVarName.playMode.toString(), playMode);
        varPlayMode.setOwner(null);
        varPlayMode.setPrivate(true);
        varPlayMode.setGlobal(true);
        
        String ownerName = user.getVariable(UserVarName.displayname.toString()).getStringValue();
        
        RoomVariable varOwner= new SFSRoomVariable(RoomVarName.roomOwner.toString(), ownerName);
        varOwner.setOwner(null);
        varOwner.setPrivate(true);
        varOwner.setGlobal(true);        
        
        RoomVariable varAccessToken = new SFSRoomVariable(RoomVarName.access_token.toString(), access_token);
        varAccessToken.setOwner(null);
        varAccessToken.setHidden(true);
        varAccessToken.setPrivate(true);
        
        RoomVariable varPlatformRoomId = new SFSRoomVariable(RoomVarName.room_id.toString(), platform_room_id);
        varPlatformRoomId.setOwner(null);
        varPlatformRoomId.setHidden(true);
        varPlatformRoomId.setPrivate(true);
        
        RoomVariable varTransactionId = new SFSRoomVariable(RoomVarName.transaction_id.toString(), transaction_id);
        varTransactionId.setOwner(null);
        varTransactionId.setHidden(true);
        varTransactionId.setPrivate(true);
        
        RoomVariable varIsDebug = new SFSRoomVariable(RoomVarName.is_auto.toString(), PlatformConfig.configMap.get(PlatformConfig.IS_AUTO));
        varIsDebug.setOwner(null);
        varIsDebug.setHidden(true);
        varIsDebug.setPrivate(true);
        
        RoomVariable varInitScore = new SFSRoomVariable(RoomVarName.init_score.toString(), PlatformConfig.configMap.get(PlatformConfig.INIT_SCORE));
        varInitScore.setOwner(null);
        varInitScore.setHidden(true);
        varInitScore.setPrivate(true);
        
        RoomVariable varTutorialBalance = new SFSRoomVariable(RoomVarName.tutorial_balance.toString(), PlatformConfig.configMap.get(PlatformConfig.TUTORIAL_BALANCE));
        varTutorialBalance.setOwner(null);
        varTutorialBalance.setHidden(true);
        varTutorialBalance.setPrivate(true);
        
        RoomVariable varTurnTime = new SFSRoomVariable(RoomVarName.turn_time.toString(), PlatformConfig.configMap.get(PlatformConfig.TURN_TIME));
        varTurnTime.setOwner(null);
        varTurnTime.setHidden(true);
        varTurnTime.setPrivate(true);
        
        RoomVariable varInitBonusTime = new SFSRoomVariable(RoomVarName.init_bonus_time.toString(), PlatformConfig.configMap.get(PlatformConfig.INIT_BONUS_TIME));
        varInitBonusTime.setOwner(null);
        varInitBonusTime.setHidden(true);
        varInitBonusTime.setPrivate(true);
        
        RoomVariable varServerMode = new SFSRoomVariable(PlatformConfig.SERVER_MODE, PlatformConfig.configMap.get(PlatformConfig.SERVER_MODE));
        varServerMode.setOwner(null);
        varServerMode.setHidden(true);
        varServerMode.setPrivate(true);
        
        RoomVariable varPlatformUrl = new SFSRoomVariable(PlatformConfig.PLATFORM_URL, PlatformConfig.configMap.get(PlatformConfig.PLATFORM_URL));
        varPlatformUrl.setOwner(null);
        varPlatformUrl.setHidden(true);
        varPlatformUrl.setPrivate(true);
        
        RoomVariable varXGameId = new SFSRoomVariable(PlatformConfig.X_GAME_ID, PlatformConfig.configMap.get(PlatformConfig.X_GAME_ID));
        varXGameId.setOwner(null);
        varXGameId.setHidden(true);
        varXGameId.setPrivate(true);
        
        RoomVariable varXSecretKey = new SFSRoomVariable(PlatformConfig.X_SECRET_KEY, PlatformConfig.configMap.get(PlatformConfig.X_SECRET_KEY));
        varXSecretKey.setOwner(null);
        varXSecretKey.setHidden(true);
        varXSecretKey.setPrivate(true);
        
        /*
         * Simulate tiles for each player
         */        
        RoomVariable varPlayer1 = new SFSRoomVariable(RoomVarName.player1.toString(), PlatformConfig.configMap.get(PlatformConfig.PLAYER1));
        varPlayer1.setOwner(null);
        varPlayer1.setHidden(true);
        varPlayer1.setPrivate(true);
        
        RoomVariable varPlayer2 = new SFSRoomVariable(RoomVarName.player2.toString(), PlatformConfig.configMap.get(PlatformConfig.PLAYER2));
        varPlayer2.setOwner(null);
        varPlayer2.setHidden(true);
        varPlayer2.setPrivate(true);
        
        RoomVariable varPlayer3 = new SFSRoomVariable(RoomVarName.player3.toString(), PlatformConfig.configMap.get(PlatformConfig.PLAYER3));
        varPlayer3.setOwner(null);
        varPlayer3.setHidden(true);
        varPlayer3.setPrivate(true);
        
        RoomVariable varPlayer4 = new SFSRoomVariable(RoomVarName.player4.toString(), PlatformConfig.configMap.get(PlatformConfig.PLAYER4));
        varPlayer4.setOwner(null);
        varPlayer4.setHidden(true);
        varPlayer4.setPrivate(true);
        
        /*
         * Simulate the picking tile
         */
        RoomVariable varPick1 = new SFSRoomVariable(RoomVarName.pick1.toString(), PlatformConfig.configMap.get(PlatformConfig.PICK1));
        varPick1.setOwner(null);
        varPick1.setHidden(true);
        varPick1.setPrivate(true);
        
        RoomVariable varPick2 = new SFSRoomVariable(RoomVarName.pick2.toString(), PlatformConfig.configMap.get(PlatformConfig.PICK2));
        varPick2.setOwner(null);
        varPick2.setHidden(true);
        varPick2.setPrivate(true);
        
        RoomVariable varPick3 = new SFSRoomVariable(RoomVarName.pick3.toString(), PlatformConfig.configMap.get(PlatformConfig.PICK3));
        varPick3.setOwner(null);
        varPick3.setHidden(true);
        varPick3.setPrivate(true);
        
        RoomVariable varPick4 = new SFSRoomVariable(RoomVarName.pick4.toString(), PlatformConfig.configMap.get(PlatformConfig.PICK4));
        varPick4.setOwner(null);
        varPick4.setHidden(true);
        varPick4.setPrivate(true);        
                        	
		CreateRoomSettings crSetting = new CreateRoomSettings();
		crSetting.setMaxUsers(MAX_PLAYER);
		crSetting.setMaxSpectators(MAX_SPECTATOR);
		crSetting.setGame(true);
		crSetting.setName(roomName);
		crSetting.setDynamic(true);
		crSetting.setGroupId("games");
		crSetting.setMaxVariablesAllowed(Integer.valueOf(PlatformConfig.configMap.get(PlatformConfig.MAX_ROOM_VARIABLES)));
		crSetting.setAutoRemoveMode(SFSRoomRemoveMode.WHEN_EMPTY);
		crSetting.setRoomVariables(Arrays.asList(varRoomBet, varAccessToken, varPlatformRoomId, varTransactionId, varState
													, varPlayMode, varOwner, varIsDebug, varInitScore, varTutorialBalance, varTurnTime, varInitBonusTime
													, varServerMode, varPlatformUrl, varXGameId, varXSecretKey
													, varPlayer1, varPlayer2, varPlayer3, varPlayer4
													, varPick1, varPick2, varPick3, varPick4));			
		
		RoomExtensionSettings reSetting = new RoomExtensionSettings(PlatformConfig.configMap.get(PlatformConfig.DYNAMIC_ROOM_NAME), MahjongExtension.class.getName());
		crSetting.setExtension(reSetting);
		
		if(roomPassword != null && roomPassword.length() > 0) {
			crSetting.setPassword(roomPassword);
		}
		
		try
		{				
			getApi().createRoom(getParentExtension().getParentZone(), crSetting, user, true, null);					
		} 
		catch(Throwable t) {			
			response = new SFSObject();
			response.putUtfString(MObject.message.toString(), "Failed in SFS API.");
			send(GameActionType.create_fail.toString(), response, user);
			
			trace(ExtensionLogLevel.ERROR, t.toString());
		}
				
		trace(ExtensionLogLevel.INFO, GameActionType.create.toString() + ": Owner " + user.getName() + "("+user.getId()+")");
	}
}
